<template>
  <!-- Grubbs图  -->
  <div id="QcGrubbChart">
    <Splitpanes horizontal>
      <Pane size="66">
        <el-scrollbar style="height: 100%; width: 100%">
          <div id="grubbchart">
            <div
              ref="piechart"
              id="chartmain"
              :style="{
                width: '100%',
                height: '500px'
              }"
              v-show="chartData"
              v-loading="loading"
            ></div>
          </div>
        </el-scrollbar>
      </Pane>
      <Pane size="34">
        <vxe-table
          ref="grubbTable"
          v-loading="loading"
          border
          align="center"
          class="mytable-scrollbar bottomTable"
          height="auto"
          :data="chartData"
          :row-config="{ isCurrent: true, isHover: true }"
          :keyboard-config="{
            isArrow: true,
            isTab: true,
            isEdit: true
          }"
          resizable
          show-overflow
        >
          <vxe-column type="seq" title="序号" width="30"></vxe-column>
          <vxe-column field="qcDate" title="检测日期" width="80">
            <template #default="{ row }">
              <span>{{ formatDateTime(row.qcDate, 'yyyy-MM-dd') }}</span>
            </template>
          </vxe-column>
          <vxe-column field="n" title="次数" width="30" header-align="center"></vxe-column>
          <vxe-column field="result" title="结果" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{
                row.result && row.result !== 'NaN' ? parseFloat(row.result).toFixed(3) : ''
              }}</span>
            </template>
          </vxe-column>
          <vxe-column field="mean" title="X" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{ row.mean && row.mean !== 'NaN' ? row.mean.toFixed(3) : '' }}</span>
            </template>
          </vxe-column>
          <vxe-column field="sd" title="SD" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{ row.sd && row.sd !== 'NaN' ? row.sd.toFixed(3) : '' }}</span>
            </template>
          </vxe-column>
          <vxe-column field="siMax" title="SI上限" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{ row.siMax && row.siMax !== 'NaN' ? row.siMax.toFixed(3) : '' }}</span>
            </template>
          </vxe-column>
          <vxe-column field="siMin" title="SI下限" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{ row.siMin && row.siMin !== 'NaN' ? row.siMin.toFixed(3) : '' }}</span>
            </template>
          </vxe-column>
          <vxe-column title="状态" width="40" align="center">
            <template #default="{ row }">
              <span
                :style="{
                  color: row.isAlarm ? '#e6a23c' : row.isOutControl ? 'red' : ''
                }"
              >
                {{ row.isAlarm ? '警告' : row.isOutControl ? '失控' : '在控' }}
              </span>
            </template>
          </vxe-column>
          <vxe-column field="n2s" title="n2s" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{ row.n2s && row.n2s !== 'NaN' ? row.n2s.toFixed(3) : '' }}</span>
            </template>
          </vxe-column>
          <vxe-column field="n3s" title="n3s" width="70" header-align="center" align="right">
            <template #default="{ row }">
              <span>{{ row.n3s && row.n3s !== 'NaN' ? row.n3s.toFixed(3) : '' }}</span>
            </template>
          </vxe-column>
        </vxe-table>
      </Pane>
    </Splitpanes>
    <vxe-modal
      v-model="modalShow"
      id="GrubbsTip"
      width="80%"
      height="80%"
      min-width="460"
      min-height="320"
      show-footer
      show-zoom
      resize
    >
      <template #title>
        <span>Grubbs图例说明</span>
      </template>
      <template #default>
        <div>
          <p>
            Grubbs法适用于试剂有效期短，批号更换频繁或不常开展的检验项目。这些项目如按常规RCV作图原则进行室内质控，得到平均数和标准差有很大难度，用Grubbs法，仅需连测3次，即可对结果进行检验和控制。而L-J图法需用同批号的试剂和质控物连测20次。
          </p>
          <p>
            Grubbs法是一种离群值检验的统计方法，一组测定值中明显偏离测定值群体的过大值或过小值称为离群值，它既可能是测定结果随机波动的极值，也可能是与群体测定值非属同质总体的异常值。如事先给定一个小概率事件临界点作为随机因素影响的最大波动值（即SI界值表），凡测定偏差超过临界值的离群值将被视为异常值，反之则视为极值加以保留。
          </p>
          <p>
            在n≥3时，计算出均值、标准差，再根据公式算出SI值，将其值与SI界值作比较。当SI上限和SI下限值小于n2s时，表示处于控制范围之内，可以继续进行测定，并重复以上计算；当SI上限和SI下限有一值处于n2s和n3s值之间时，说明该值在2～3s范围，处于“警告”状态；当SI上限和SI下限有一值大于n3s时，说明该值已在3s范围之外，属“失控”。数字处于“警告”和“失控”状态应舍去，重新测定该质控品和病人样本。
          </p>
        </div>
      </template>
    </vxe-modal>
  </div>
</template>
<script lang="ts" setup>
import { ref, Ref, reactive, getCurrentInstance, onMounted } from 'vue';
import { Splitpanes, Pane } from 'splitpanes';
import { ECharts, EChartsOption, init, color } from 'echarts';
import { IsEmpty, formatDateTime } from '@/utils/common';

defineExpose({
  getEchartData
});

// 变量定义区
let { proxy }: any = getCurrentInstance();

let chartData = reactive([]);
let chart: ECharts;
const piechart: Ref<HTMLElement | null> = ref(null);
const resultForm = reactive({
  rptGroupId: null, //报告单元id
  rptGroupName: '',
  // selectWorkTeam: '', //选中的子工作组id
  insId: null, //仪器
  insName: '',
  insAnsId: null, //仪器项目
  itemDictId: null, //项目
  ansName: '',
  iqcMaterialIds: [],
  QCDateS: null, //开始时间
  QCDateE: null //结束时间
});
let chartHeight: number = ref(400);
let modalShow = ref(false);

onMounted(() => {});

// 方法定义区
function getEchartData(iqcResultForm: any, chartHeight: number) {
  Object.assign(resultForm, iqcResultForm);
  chartData.length = 0;
  if (resultForm.iqcMaterialIds.length === 0) {
    clearCanvas();
    return;
  }

  let url = '/api/qc/chart/getGrubbsData';
  let obj = {
    itemDictId: resultForm.itemDictId,
    QcMaterialIds: resultForm.iqcMaterialIds,
    QCDateS: resultForm.QCDateS,
    QCDateE: resultForm.QCDateE
  };
  proxy.$http
    .get(url, { params: obj })
    .then((res: any) => {
      if (res.data.length > 0) {
        chartData.push(...res.data);
        initChart(chartData);
      } else {
        clearCanvas();
      }
    })
    .catch((err) => {
      proxy.$alert(err, '提示');
      // this.loading = false;
    });
}

// 清除画布
function clearCanvas() {
  const myChart = init(piechart.value as HTMLElement);
  myChart.clear(); // 清除画布
}

function initChart(chartData: any) {
  // 图表宽度自适应
  const chartBox = document.getElementById('grubbchart');
  const chartDom = document.getElementById('chartmain');
  //图表宽高计算
  chartssize(chartBox, chartDom);
  const myChart = init(piechart.value as HTMLElement);

  const yAxisData = ['0.00', '0.50', '1.00', '1.50', '2.00', '2.50', '3.00', '3.50'];
  const xAxisData = [];
  const n2sData = [];
  const n3sData = [];
  const siMinData = [];
  const siMaxData = [];
  const customDataMin = []; //面积画图下限数据（二维数组，里面的数组为坐标点，下限X坐标从小到大）
  const customDataMax = []; //面积画图上限数据（二维数组，里面的数组为坐标点，上限X坐标从大到小）
  let customData = [];
  chartData.forEach((item, index) => {
    xAxisData.push(item.n);
    n2sData.push({
      qcDate: item.qcDate,
      qcSequence: item.qcSequence,
      result: item.result,
      value: IsEmpty(item.n2s) || item.n2s === 'NaN' ? null : parseFloat(item.n2s).toFixed(2)
    });
    n3sData.push(IsEmpty(item.n3s) || item.n3s === 'NaN' ? null : parseFloat(item.n3s).toFixed(2));
    if (IsEmpty(item.siMin) || item.siMin === 'NaN') {
      siMinData.push(null);
    } else {
      siMinData.push(parseFloat(item.siMin).toFixed(2));
      // 下限
      customDataMin.push([parseInt(item.n) - 1, siMinData[index]]);
    }
    if (IsEmpty(item.siMax) || item.siMax === 'NaN') {
      siMaxData.push(null);
    } else {
      siMaxData.push(parseFloat(item.siMax).toFixed(2));
      // 上限
      customDataMax.push([parseInt(item.n) - 1, siMaxData[index]]);
    }
  });
  customData = customDataMin;
  for (let i = customDataMax.length - 1; i >= 0; i--) {
    customData.push(customDataMax[i]);
  }
  const option = {
    title: {
      // text: '',
    },
    legend: {
      type: 'scroll',
      top: 10,
      itemWidth: 35,
      textStyle: {
        fontSize: 16
      }
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        // type: 'line',//指示器
      },
      confine: true, //是否将 tooltip 框限制在图表的区域内
      backgroundColor: 'rgba(255, 255, 255, 0.8)',
      borderRadius: 5,
      extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);',
      padding: [5, 10],
      textStyle: {
        color: '#333'
      },
      formatter: formatter
    },
    toolbox: {
      feature: {
        saveAsImage: {
          title: '保存为图片',
          name: 'Grubbs图-' + formatDateTime(new Date(), 'yyyy-MM-dd'),
          type: 'png'
        },
        myTipImage: {
          //自定义图标，必须以my开头
          show: true,
          title: 'Grubbs图说明',
          icon: 'path://M505.3 844.6c-6.8 0-13.9-2-19.8-5.7-6.7-4.1-11.7-8.9-14.8-14.2-3.5-6.5-5.2-13.2-5.2-20 0-11.8 3.7-21.3 11.3-28.9 8.5-7.5 17.6-10.9 28.6-10.9 11.9 0 21.2 3.5 28.5 10.8 7.6 7.6 11.4 17.1 11.4 29 0 7.3-1.7 14-5.2 19.9-3.4 5.9-8.2 10.5-14.7 14.2-6.8 3.9-13.5 5.8-20.1 5.8z m-2.8-146.8c-9.3-1.4-16.2-5.2-21.8-11.7-5.4-6.3-7.9-14.1-7.4-23.7 3.7-28.8 14-54.3 31.6-77.9 16.3-23 37-46.4 63.3-71.6l0.1-0.1c37.4-37.9 61-66.7 70.2-85.7 9.1-18.7 12.9-35.2 11.4-48.9 1.5-33.6-9.9-63.6-34-89.3-13.4-14-28.9-24.7-47.3-32.8-18.3-7.5-37.2-11.3-56.5-11.3-39.3 0.5-71.3 13.7-97.9 40.3-25.2 25.7-38.7 58.2-40.3 96.7v0.2c0 9.6-3.1 17.7-9.3 23.8-6.2 6.2-14 9.3-23.3 9.3-9.9 0-17.5-3-23.2-9.2l-0.1 0.1c-6.1-6.1-9.3-13.9-9.8-23.9 0-27.3 5.2-53.3 15.3-77.2 10.1-24.2 24.7-45.7 44.6-65.6 19.9-19.9 41.4-34.5 65.6-44.6 24.8-10.3 50.1-15.4 77.3-15.4 28.7 0 56.6 5.5 83.1 16.4 26 10.7 49.2 26.7 69.1 47.6 18.8 18.8 32.7 40.3 41.5 63.9 8.7 23.4 12.3 48.5 10.7 74.6v0.4c0.5 21.5-5.2 44.9-17.4 71.3-12.1 25.7-40.1 61.2-83.3 105.4-23.3 22.7-40.8 42-53.6 58.9-13 17.2-20.5 34.1-22.2 50.4-1.5 9-4.9 15.7-10.8 21.1-6 5.5-13.3 8.3-21.8 8.3h-3.8z',
          onclick: () => {
            modalShow.value = true;
          }
        }
      },
      right: 20
    },
    grid: {
      top: '50px',
      bottom: '70px',
      left: '50px',
      right: '50px'
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      splitLine: {
        show: true
      },
      // splitNumber: 31,
      axisLabel: {
        interval: 0
      }, //强制显示所有坐标
      data: xAxisData
    },
    yAxis: {
      type: 'value',
      data: yAxisData,
      max: yAxisData[yAxisData.length - 1], //坐标轴刻度最大值
      min: yAxisData[0],
      splitNumber: yAxisData.length //坐标轴的分割段数
    },
    dataZoom: [
      {
        type: 'slider',
        start: 0,
        end: 100,
        height: 18,
        filterMode: 'empty',
        showDataShadow: false
      },
      {
        type: 'inside',
        start: 0,
        end: 100
      }
    ], //区域缩放
    series: [
      {
        name: 'n2s',
        type: 'line',
        symbol: 'circle',
        symbolSize: 1,
        data: n2sData,
        color: 'blue',
        connectNulls: true //断点链接
      },
      {
        name: 'n3s',
        type: 'line',
        symbol: 'circle',
        symbolSize: 1,
        data: n3sData,
        color: 'red',
        connectNulls: true //断点链接
      },
      {
        type: 'custom',
        renderItem: function (params, api) {
          if (params.context.rendered) {
            return;
          }
          params.context.rendered = true;
          let points = [];
          for (let i = 0; i < customData.length; i++) {
            points.push(api.coord(customData[i]));
          }
          // let color = api.visual('color');
          return {
            type: 'polygon',
            transition: ['shape'],
            shape: {
              points: points
            },
            style: api.style({
              fill: 'rgba(64, 158, 255, 0.3)',
              stroke: color.lift('#e6a23c', 0.1)
            })
          };
        },
        clip: true,
        data: customData //面积画图数据
      },
      {
        name: 'siMin',
        type: 'line',
        data: siMinData,
        color: '#67c23a',
        connectNulls: true //断点链接
      },
      {
        name: 'siMax',
        type: 'line',
        data: siMaxData,
        // symbolSize: 10,
        color: '#409eff',
        connectNulls: true //断点链接
      }
    ]
  };

  myChart.setOption(option, true); //第二个参数 true 用来清除上次数据
}

function chartssize(container, charts) {
  const w = '100%';
  const h = '300px';
  charts.style.width = w;
  charts.style.hight = h;
  return { width: w, height: h };
}

function formatter(params, ticket, callback) {
  let str =
    '时间：' +
    formatDateTime(params[0].data.qcDate, 'yyyy-MM-dd') +
    '<br />次数：' +
    params[0].data.qcSequence +
    '<br />结果：' +
    params[0].data.result +
    '<br />';
  for (let i = 0; i < params.length; i++) {
    if (!IsEmpty(params[i].data) && params[i].seriesType !== 'custom') {
      str += '<div>';
      str +=
        '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' +
        params[i].color +
        ';"></span>' +
        params[i].seriesName +
        '：';

      str +=
        '<span style="font-weight:bold;display: inline-block;width: 60px;margin-right:8px;">' +
        params[i].value +
        '</span>';

      str += '</div>';
    }
  }
  return str;
}
</script>
<style lang="scss" scoped>
#QcGrubbChart {
  height: 100%;
  .chart {
    width: 100%;
    height: 400px;
  }
  .bottomTable {
    height: 100%;
  }
}
</style>
